<?php
declare (strict_types=1);

namespace app\common\job;

use app\admin\model\wechat\Account as AccountModel;
use app\admin\model\wechat\Article as ArticleModel;
use app\admin\model\wechat\Auth as AuthModel;

use think\facade\Cache;
use think\facade\Db;
use think\queue\Job;
use app\common\library\wechat\Crawler;

class Wechat
{

    /**
     * @var AccountModel
     */
    protected $AccountModel;
    /**
     * @var ArticleModel
     */
    protected $ArticleModel;

    public function __construct()
    {
        $this->AccountModel = new AccountModel;
        $this->ArticleModel = new ArticleModel;
    }

    /**
     * @param Job $job
     * @param $data
     */
    public function fire(Job $job, $data)
    {
        //启动redis
        //redis-server.exe redis.windows.conf

        //启动队列
        //php think queue:work --queue WechatQueue --tries=3

        //任务名称
        $jobName = $job->getName();
        $jobId = $job->getJobId();

        //队列日志
        $model = new \app\common\model\QueueLog();
        $queue = $model->withTrashed()->where('id', '=', $jobId)->find();
        if (!$queue || $queue['status'] == 40) {
            $job->delete();
        } else {
            //....这里执行具体的任务
            if ($data['type'] == 'history') {
                $result = $this->history($data);
            } elseif ($data['type'] == 'latest') {
                $result = $this->latest($data);
            } else {
                $result = true;
            }
            if ($result) {
                echo "执行成功\n";
                $queue->save(['status' => 20]);
                //任务执行成功后，删除任务
                $job->delete();

            } else {
                echo "执行失败\n";
                $queue->inc('attempts', 1)->update(['status' => 30]);
                if ($job->attempts() > 3) {
                    //通过这个方法可以检查这个任务已经重试了几次了
                    //直到达到最大重试次数后失败后，执行failed方法
                    $job->delete();
                } else {
                    // 重新发布这个任务
                    //$delay = 60 * 60 * $job->attempts();
                    $delay = pow(60, $job->attempts());

                    $execution_time = time() + $delay;
                    $queue->save(['execution_time' => $execution_time]);

                    $job->release($delay); //$delay为延迟时间
                }
            }
        }
        Db::__destruct();
    }

    /*
     * 采集公众号历史文章
     */
    protected function history($data)
    {
        $fakeid = $data['fakeid'];
        $begin = $data['begin'];
        $finish = $data['finish'];
        $query = $data['query'];

        $account = $this->AccountModel->where('fakeid', '=', $fakeid)->find();
        if ($account) {
            list($token, $cookie) = AuthModel::getAuthInfo();

            $crawler = new Crawler();

            $crawler->setToken($token);
            $crawler->setCookie($cookie);

            $result = $crawler->getAccountAppMsg($fakeid, $begin, $query);
            if ($result == false) {
                if ($crawler->getErrorCode() == '200003') {
                    AuthModel::updateAuth($token);
                }
                return false;
            }
            list($total, $list) = $result;
            //文章数量
            $account->save(['msg_count' => $total]);
            //没有文章了
            if (empty($list)) {
                return true;
            }
            $this->ArticleModel->saveArticleList($list, $account);
            $data['begin'] += 5;
            if ($data['begin'] % 25 == 0) {
                $delay = 60;
            } else {
                $delay = mt_rand(5, 10);
            }
            //结束
            if ($data['begin'] >= $finish) {
                return true;
            }
            //添加下一阶段
            add_wechat_queue($data, $delay);
            return true;

        } else {
            return false;
        }
    }

    /*
     * 采集公众号最新文章
     */
    protected function latest($data)
    {
        $fakeid = $data['fakeid'];
        $begin = 0;
        $finish = 5;
        $query = '';
        $source = $data['source'];

        //采集控制-防止采集队列在同一时间过多
        $key = 'wechat_queue_article';
        $cache = Cache::get($key);
        if (empty($cache)) {
            Cache::set($key, $fakeid, 30);
        } else {
            $delay = 30;
            add_wechat_queue($data, $delay);
            return true;
        }

        $account = $this->AccountModel->where('fakeid', '=', $fakeid)->find();
        if ($account) {
            //添加下一阶段
            if ($source == 'queue') {
                $delay = mt_rand(3000, 4200);
                add_wechat_queue($data, $delay);
            }

            list($token, $cookie) = AuthModel::getAuthInfo();

            $crawler = new Crawler();

            $crawler->setToken($token);
            $crawler->setCookie($cookie);

            $result = $crawler->getAccountAppMsg($fakeid, $begin, $query);
            if ($result == false) {
                if ($crawler->getErrorCode() == '200003') {
                    AuthModel::updateAuth($token);
                }
                //返回true,让队列一直执行
                return true;
            }
            list($total, $list) = $result;
            //文章数量
            $account->save(['msg_count' => $total]);
            //没有文章了
            if (empty($list)) {
                return true;
            }
            $this->ArticleModel->saveArticleList($list, $account);

            return true;

        } else {
            return false;
        }
    }

    public function failed($data)
    {

        // ...任务达到最大重试次数后，失败了
    }

}
